package org.suigara.jd.request;

import static org.suigara.jd.utils.HttpClientUtils.doGetString;
import static org.suigara.jd.utils.HttpClientUtils.getContentString;

import java.io.IOException;
import java.io.InputStream;
import java.net.URISyntaxException;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.apache.http.Header;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.NameValuePair;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.protocol.HTTP;
import org.json.JSONException;
import org.json.JSONObject;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;
import org.suigara.jd.Setting;
import org.suigara.jd.bean.AuctionInfo;
import org.suigara.jd.bean.GoodsInfo;
import org.suigara.jd.constants.JDURLConsts;
import org.suigara.jd.exception.IgnorException;
import org.suigara.jd.log.Logger;
import org.suigara.jd.utils.HttpClientUtils;

public class JDSession {
	private String userName;
	private String password;

	private static String redirectURL = "http://order.jd.com/center/list.action";
	private static String loginUrl = "https://passport.jd.com/uc/login";
	private static String renRenLoginURL = "https://passport.jd.com/uc/loginService";

	// The HttpClient is used in one session
	private CloseableHttpClient httpclient = HttpClients.createDefault();;

	public JDSession() {
		super();

	}

	public static void main(String[] args) throws IOException,
			URISyntaxException {
		String source = "<a title=中国体育报 href=''>aaa</a><a title='北京日报' href=''>bbb</a>";
		List<String> list = match(source, "a", "title");
		System.out.println(list);
	}

	private boolean login = false;

	public boolean login(AuthCodeListener l) {
		try {
			userName = Setting.getUserName();
			password = Setting.getPassword();
			login = loginImpl(l);

		} catch (Exception e) {
			Logger.error(e);
			login = false;
		}
		return login;
	}

	@SuppressWarnings("deprecation")
	private boolean loginImpl(AuthCodeListener l) {
		Map<String, String> map = getParams(l);

		HttpPost httpost = new HttpPost(renRenLoginURL + "?uuid="
				+ map.get("uuid") + "&ltype=logout&r=" + Math.random()+"&version=2015");
		List<BasicNameValuePair> nvps = new ArrayList<BasicNameValuePair>();
		Iterator<String> it = map.keySet().iterator();
		while (it.hasNext()) {
			String key = it.next();
			String value = map.get(key);
//			System.out.println(key+"=>"+value);
			nvps.add(new BasicNameValuePair(key, value));
		}

		try {
			// RequestConfig requestConfig = RequestConfig.custom()
			// .setCookieSpec(CookieSpecs.BEST_MATCH).build();
			// httpost.setConfig(requestConfig);
			// httpclient.getParams().setParameter(ClientPNames.COOKIE_POLICY,
			// CookiePolicy.BEST_MATCH);
			httpost.setEntity(new UrlEncodedFormEntity(
					(List<? extends NameValuePair>) nvps, HTTP.UTF_8));
			HttpResponse response = httpclient.execute(httpost);
			
			String result = getContentString(response.getEntity().getContent());
			boolean loginSuccess = result.contains("success")
					&& result.contains(redirectURL);
			if (!loginSuccess) {
				Logger.info("登录失败:" + result);
			} else {
				Header[] headers = response.getHeaders("Set-Cookie");
				for (Header header : headers) {
					Logger.info(header.getValue());
				}
			}
			return loginSuccess;
		} catch (Exception e) {
			Logger.error(e);
			return false;
		} finally {
			httpost.abort();
		}
	}

	public boolean doPrice(GoodsInfo goods, int newPrice) {
		if (login) {
			long time = Calendar.getInstance().getTime().getTime();

			try {
				JSONObject json = doGetJson2(httpclient,
						JDURLConsts.AUCTION_URL + "services/bid.action?t="
								+ time + "&paimaiId=" + goods.getGoodsId()
								+ "&price=" + newPrice
								+ "&proxyFlag=0&bidSource=0",
						JDURLConsts.AUCTION_URL + goods.getGoodsId());

				String message = json.getString("message");
				boolean success = message != null
						&& json.getString("message").contains("出价成功!");
				if (!success) {
					String errorMsg = message;
					Logger.info("[" + goods.getGoodsId() + "]" + errorMsg);
				}
				return success;
			} catch (Exception e) {
				Logger.error(e);
				UnSessionUtils.doPriceWithBrowser(goods, newPrice);
				return true;
			}
		} else {
			UnSessionUtils.doPriceWithBrowser(goods, newPrice);
			return true;
		}
	}

	private static JSONObject doGetJson2(CloseableHttpClient httpclient,
			String url, String oldUrl) {
		HttpGet httpGet = new HttpGet(url);
		httpGet.setHeader("Referer", oldUrl);//
		CloseableHttpResponse response = null;
		try {
			response = httpclient.execute(httpGet);
			if (response.getStatusLine().getStatusCode() != 200) {
				throw new RuntimeException("errorcode="
						+ response.getStatusLine().getStatusCode());
			}
			
			HttpEntity httpEntity = response.getEntity();

			if (httpEntity == null) {
				throw new RuntimeException("httpEntity=null");
			}
			InputStream content = httpEntity.getContent();
			String str = getContentString(content);
			content.close();

			JSONObject jsobj = new JSONObject(str);
			return jsobj;
		} catch (IOException e) {
			throw new IgnorException(e);
		} catch (JSONException e) {
			Logger.error(e);
			throw new RuntimeException(e);
		} finally {
			if (httpGet != null) {
				httpGet.completed();
			}
			if (response != null) {
				try {
					response.close();
				} catch (IOException localIOException2) {
				}
			}

		}
	}

	public List<AuctionInfo> getAuctionResult() {
		Document doc = HttpClientUtils.doGetHtml(httpclient,
				JDURLConsts.MY_AUCTION_URL);
		Elements elements = doc.getElementsByClass("tb-void");
		List<AuctionInfo> myGoods = new ArrayList<AuctionInfo>();
		if (elements.size() == 0) {
			Logger.debug("未登录！！！！！");
			return myGoods;
		}
		Element table = elements.get(0);
		Elements rows = table.getElementsByTag("tr");
		int rowCnt = rows.size();

		for (int i = 0; i < rowCnt; i++) {
			Element rowData = rows.get(i);
			Elements headers = rowData.getElementsByTag("th");
			if (headers.size() > 0) {
				continue;
			}
			// <th width="100">商品名称</th>
			//
			// <th width="120">夺宝编号</th>
			// <th width="130">交易类型</th>
			// <th width="130">交易价格</th>
			// <th width="130">交易时间</th>
			// <th width="92">状态</th>
			// <th width="140">操作</th>

			Elements cells = rowData.getElementsByTag("td");

			/**
			 * <td>
			 * 
			 * 
			 * <span class="useIcon ui1"></span>
			 * 
			 * <a href="http://paimai.jd.com/10577907" target="_blank"
			 * class="pic"><img width="100" height="100" class="err-product"
			 * src=
			 * "http://img11.360buyimg.com/n1/jfs/t1039/4/855397286/67354/bbe028/55533041N1a376b27.jpg"
			 * ></a> <span class="name"> <a href="http://paimai.jd.com/10577907"
			 * target="_blank" title="贝亲（Pigeon）哺喂勺组 DA39">贝亲（Pigeon）哺喂勺组
			 * DA39</a> </span> <span class="serialNum">竞拍编号：10577907</span>
			 * <span class="offer gray"> </span></td>
			 */
			Element idElement = cells.get(0);
			String idTextAll = idElement.getElementsByClass("serialNum").get(0)
					.text();
			String goodsId = idTextAll.split("：")[1].trim();
			String goodsName = idElement.getElementsByClass("name").get(0)
					.child(0).attr("title");
			String picUrl = idElement.getElementsByTag("img").get(0)
					.attr("src");

			Element priceElement = cells.get(2);
			String priceStr = priceElement.text().replaceAll("¥", "");

			Element timeElement = cells.get(1);
			String timeStr = timeElement.child(0).text().trim();

			Element statusElement = cells.get(3);
			String statusStr = statusElement.child(0).text().trim();
			if (statusStr.equals("完成")) {
				continue;
			}
			myGoods.add(new AuctionInfo(goodsId, goodsName, statusStr, timeStr,
					priceStr, picUrl));
		}

		return myGoods;
	}

	private Map<String, String> getParams(AuthCodeListener l) {
		Map<String, String> map = new HashMap<String, String>();
		map.put("ReturnUrl", redirectURL);
		map.put("loginname", userName);
		map.put("nloginpwd", password);
		map.put("loginpwd", password);

		// uuid and cookie
		String str = doGetString(httpclient, loginUrl);
		Document doc = Jsoup.parse(str);
		Element authcode = doc.getElementById("o-authcode");
		Element authcodeImg = authcode.getElementsByTag("img").get(0);
		String authCodeUrl = authcodeImg.attr("src");
		if (authCodeUrl == null || authCodeUrl.isEmpty()) {
			authCodeUrl = authcodeImg.attr("src2");
		}
		String authCodeStr = l.authCode(authCodeUrl);
		map.put("authcode", authCodeStr.toString());
		String strs1[] = str.split("name=\"uuid\" value=\"");
		String strs2[] = strs1[1].split("\"/>");
		String uuid = strs2[0];
		map.put("uuid", uuid);

		Elements inputs = doc.getElementsByTag("input");
		for (int i = 0; i < inputs.size(); i++) {
			Element input = inputs.get(i);
			String type = input.attr("type");
//			System.out.println("input="+input);
			if ("hidden".equalsIgnoreCase(type)) {
				String name = input.attr("name");
				String value = input.attr("value");
				if (value == null || value.isEmpty()) {
					continue;
				}
				map.put(name, value);
			}
		}
		return map;
	}

	public static List<String> match(String source, String element, String attr) {
		List<String> result = new ArrayList<String>();
		String reg = "<" + element + "[^<>]*?\\s" + attr
				+ "=['\"]?(.*?)['\"]?\\s.*?>";
		Matcher m = Pattern.compile(reg).matcher(source);
		while (m.find()) {
			String r = m.group(1);
			result.add(r);
		}
		return result;
	}

	public void closeSession() {
		try {
			httpclient.close();
		} catch (IOException e) {
			Logger.error(e);
		}
	}
}

